home *** CD-ROM | disk | FTP | other *** search
- /* File: ASM.c */
-
- #include <Errors.h>
- #include <SetUpA4.h>
- #include <A4Stuff.h>
- #include <Icons.h>
- #include "iconsextra.h"
-
- #define ICON_SUCCESS 1025
- #define ICON_FAILURE 1026
- #define MyMenuID -16509
- #define MyIconFamilyID 1024
-
-
- // Special Undocumented Routines for System Mode
- pascal OSErr TurnSystemModeOn(void) = {0x3F3C, 0x0040, 0xA88F};
- pascal OSErr TurnSystemModeOff(void) = {0x3F3C, 0x0041, 0xA88F};
-
-
- long gSystemMenuAddress;
- long gDrawMenuBarAddress;
- long gMenuSelectAddress;
- long gMenuKeyAddress;
- long gSetItemAddress;
- long gInsertMenuAddress;
- FSSpec gInitFSSpec; /* An FSSpec to this file (so we can get at it later) */
- MenuHandle gMenuHandle; /* Our menu, as skanky as it is */
- Handle gIconSuite; /* The icon suite for the title of our menu */
- MenuHandle gHelpMenu;
- Boolean gMenuInstalled; /* Have we set up our menu yet? */
-
-
- // prototypes
- typedef pascal void (*DrawMenuBarProcPtr) ();
- #define callDrawMenuBar(userRoutine) \
- (*(DrawMenuBarProcPtr)(userRoutine))()
-
- typedef pascal long (*MenuSelectProcPtr) (Point startPt);
- #define callMenuSelect(userRoutine, startPt) \
- (*(MenuSelectProcPtr)(userRoutine))((startPt))
-
- typedef pascal long (*MenuKeyProcPtr) (short ch);
- #define callMenuKey(userRoutine, ch) \
- (*(MenuKeyProcPtr)(userRoutine))((ch))
-
- typedef pascal void (*SystemMenuProcPtr) (long menuResult);
- #define callSystemMenu(userRoutine, menuResult) \
- (*(SystemMenuProcPtr)(userRoutine))((menuResult))
-
- typedef pascal void (*SetMenuItemProcPtr) (MenuRef menuH, short item, ConstStr255Param itemString);
- #define callSetMenuItemText(userRoutine, menuH, item, itemString) \
- (*(SetMenuItemProcPtr)(userRoutine))((menuH), (item), (itemString))
-
- typedef pascal void (*InsertMenuProcPtr) (MenuRef menuH, short beforeID);
- #define callInsertMenu(userRoutine, menuH, beforeID) \
- (*(InsertMenuProcPtr)(userRoutine))((menuH), (beforeID))
-
-
-
- extern pascal void ShowIcon7( short iconId, Boolean advance );
- static OSErr GetFileFromRefNum (short fRefNum, short *volID, long *dirID, StringPtr name);
- pascal void MyDrawMenuBar(void);
- pascal void MySystemMenu(long MenuCode);
- pascal long MyMenuSelect(Point startPt);
- pascal long MyMenuKey(short theChar);
- pascal long MyMenuKey(short theChar);
- pascal void MySetMenuItemText(MenuRef theMenu, short item, ConstStr255Param itemString);
- pascal void MyInsertMenu(MenuRef theMenu, short beforeID);
-
- pascal void main()
- {
- Handle initHandle;
- THz currZone;
- Handle oneIcon;
- short iconNum;
- OSErr err;
-
- EnterCodeResource();
- PrepareCallback(); // setup a4 for later usage!
-
- /* Locate this resource in memory and detach it */
- initHandle = Get1Resource('INIT', 1024);
- HNoPurge(initHandle);
- DetachResource(initHandle);
-
-
- err = GetFileFromRefNum(CurResFile(), &gInitFSSpec.vRefNum, &gInitFSSpec.parID, gInitFSSpec.name);
- if (err) { /*Debugger();*/ goto done; } /* <<< If we display an icon, this should indicate a failure */
-
- /*
- Install the trap patches
- */
- gDrawMenuBarAddress = (long)NGetTrapAddress(_DrawMenuBar, ToolTrap);
- NSetTrapAddress((UniversalProcPtr)MyDrawMenuBar, _DrawMenuBar, ToolTrap);
-
- gSystemMenuAddress = (long)NGetTrapAddress(_SystemMenu, ToolTrap);
- NSetTrapAddress((UniversalProcPtr)MySystemMenu, _SystemMenu, ToolTrap);
-
- gMenuSelectAddress = (long)NGetTrapAddress(_MenuSelect, ToolTrap);
- NSetTrapAddress((UniversalProcPtr)MyMenuSelect, _MenuSelect, ToolTrap);
-
- gMenuKeyAddress = (long)NGetTrapAddress(_MenuKey, ToolTrap);
- NSetTrapAddress((UniversalProcPtr)MyMenuKey, _MenuKey, ToolTrap);
-
- gSetItemAddress = (long)NGetTrapAddress(_SetItem, ToolTrap);
- NSetTrapAddress((UniversalProcPtr)MySetMenuItemText, _SetItem, ToolTrap);
-
- gInsertMenuAddress = (long)NGetTrapAddress(_InsertMenu, ToolTrap);
- NSetTrapAddress((UniversalProcPtr)MyInsertMenu, _InsertMenu, ToolTrap);
-
-
- currZone = GetZone();
- SetZone(SystemZone());
-
- gMenuHandle = NewMenu(MyMenuID, "\pxyzzy");
-
- // load the icon suite and then detach all entries
- if (GetIconSuite(&gIconSuite, MyIconFamilyID, svAllAvailableData) == noErr) {
- HLock(gIconSuite);
- for (iconNum = largeIcon1; iconNum <= miniIcon8; iconNum++) {
- oneIcon = (**((IconSuiteHandle)gIconSuite)).table[iconNum];
- if (oneIcon) DetachResource(oneIcon);
- }
- HUnlock(gIconSuite);
- BlockMoveData(&gIconSuite, &(**gMenuHandle).menuData[2], 4);
- (**gMenuHandle).menuData[1] = ~(**gMenuHandle).menuData[1] & 1;
- }
-
-
- SetZone(currZone);
-
- gMenuInstalled = FALSE;
-
- done:
-
- ShowIcon7( (!err ? ICON_SUCCESS : ICON_FAILURE), TRUE );
-
- ExitCodeResource();
- }
-
- static asm void saveregisters (void)
- {
- move.l (sp)+,a0 // the return address in a0
- movem.l d0-d2/a1,-(sp) // which is not saved
- jmp (a0)
- }
-
- static asm void restoreregisters (void)
- {
- move.l (sp)+,a0 // the return address in a0
- movem.l (sp)+,d0-d2/a1 // which is not restored
- jmp (a0)
- }
-
-
-
- pascal void MyDrawMenuBar(void)
- {
- long patchAddress;
-
- EnterCallback();
- saveregisters();
-
- patchAddress = gDrawMenuBarAddress;
-
- /* Install and/or update the menu */
- if (gMenuHandle) {
- OSErr err = noErr;
- MenuHandle mh;
- short i, ch;
- Str255 itemStr;
-
- // delete the old
- for (i=CountMItems(gMenuHandle);i>=1;i--) { DeleteMenuItem(gMenuHandle, i); }
-
- // append the new!
- err = HMGetHelpMenuHandle(&mh);
- if (!err && mh) {
- for(i=1;i<=CountMItems(mh);i++) {
- GetMenuItemText(mh, i, itemStr);
- AppendMenu(gMenuHandle, "\p ");
- SetMenuItemText(gMenuHandle, i, itemStr);
- GetItemCmd(mh, i, &ch);
- SetItemCmd(gMenuHandle, i, ch);
- }
-
- DeleteMenu((*mh)->menuID);
- // Remember, the memory for mh is still around, just not in the menu.
- InsertMenu(mh, hierMenu);
- gHelpMenu = mh;
- }
-
- if (!gMenuInstalled) {
- InsertMenu(gMenuHandle, 0);
- gMenuInstalled = true;
- }
- }
-
- patchDone:
- restoreregisters();
- ExitCallback();
-
- callDrawMenuBar(patchAddress);
- }
-
-
- pascal long MyMenuSelect(Point startPt)
- {
- long patchAddress;
- long menuResult;
- short menuID, itemID;
-
- EnterCallback();
- saveregisters();
-
- // Debugger();
- patchAddress = gMenuSelectAddress;
- menuResult = callMenuSelect(patchAddress, startPt);
- menuID = HiWord(menuResult); itemID = LoWord(menuResult);
- if (menuID == MyMenuID) // switch to real help menu!
- menuResult = ((long)kHMHelpMenuID << 16) + itemID;
-
-
- msdone:
- restoreregisters();
- ExitCallback();
-
- return(menuResult);
- }
-
- pascal long MyMenuKey(short theChar)
- {
- long patchAddress;
- long menuResult;
- short menuID, itemID;
-
- EnterCallback();
- saveregisters();
-
- // Debugger();
- patchAddress = gMenuKeyAddress;
- menuResult = callMenuKey(patchAddress, theChar);
- menuID = HiWord(menuResult); itemID = LoWord(menuResult);
- if (menuID == MyMenuID) // switch to real help menu!
- menuResult = ((long)kHMHelpMenuID << 16) + itemID;
-
- mkdone:
- restoreregisters();
- ExitCallback();
-
- return(menuResult);
- }
-
- /* This gets called when the user selects one of the items in a system menu */
- pascal void MySystemMenu(long menuCode)
- {
- long patchAddress;
- short menuID = HiWord(menuCode), itemID = LoWord(menuCode);
-
- EnterCallback();
- saveregisters();
-
- // save it off, if we need it!
- patchAddress = gSystemMenuAddress;
-
- // Debugger();
- if (gMenuHandle) {
- if (menuID == MyMenuID) { /* my menu was selected */
- menuCode = ((long)kHMHelpMenuID << 16) + itemID;
- }
- }
-
- smdone:
- restoreregisters();
- ExitCallback();
-
- callSystemMenu(patchAddress, menuCode);
- }
-
-
- pascal void MySetMenuItemText(MenuRef theMenu, short item, ConstStr255Param itemString)
- {
- OSErr err = noErr;
- long patchAddress;
- MenuRef hMenu;
-
- EnterCallback();
- saveregisters();
-
- // save it off, if we need it!
- patchAddress = gSetItemAddress;
-
- // err = HMGetHelpMenuHandle(&hMenu);
- hMenu = gHelpMenu;
- if (gMenuHandle && hMenu && (theMenu == hMenu) && (item <= CountMItems(gMenuHandle))) {
- // Debugger();
- // SetMenuItemText(gMenuHandle, item, itemString); // set our item too!
- theMenu = gMenuHandle;
- }
-
- smidone:
- restoreregisters();
- ExitCallback();
-
- callSetMenuItemText(patchAddress, theMenu, item, itemString);
- }
-
-
- pascal void MyInsertMenu(MenuRef theMenu, short beforeID)
- {
- OSErr err = noErr;
- long patchAddress;
- MenuRef hMenu;
-
- EnterCallback();
- saveregisters();
-
- // save it off, if we need it!
- patchAddress = gInsertMenuAddress;
-
- err = HMGetHelpMenuHandle(&hMenu);
- if (gMenuHandle && hMenu && (theMenu == hMenu)) {
- Debugger();
- beforeID = hierMenu; // get it out of main menu bar!
- }
-
- smidone:
- restoreregisters();
- ExitCallback();
-
- callInsertMenu(patchAddress, theMenu, beforeID);
- }
-
-
- /* Determine if a given trap exists */
- static Boolean TrapAvailable(long trapNum)
- {
- #define UNIMPL_TRAP 0xA89F
- long trap1, trap2;
- long numTraps;
- short trapType;
-
- /*
- First, find out how big the trap table is. It will vary on
- different machines. We assume that the trap InitGraf will always
- be implemented.
- */
- trap1 = (long)NGetTrapAddress(0xAA6E, ToolTrap);
- trap2 = (long)NGetTrapAddress(0xA86E, ToolTrap);
- if (trap1 == trap2)
- numTraps = 0x200;
- else
- numTraps = 0x400;
-
- /*
- Now, figure out what kind of trap this is, so the client
- doesn't have to worry about it.
- */
- if ((trapNum & 0x0800) > 0)
- trapType = ToolTrap;
- else
- trapType = OSTrap;
-
- /*
- Now, there are no tool box traps after a certain number,
- so we can rule those out now.
- */
- if (trapType == ToolTrap) {
- trapNum &= 0x07FF;
- if (trapNum >= numTraps)
- trapNum = UNIMPL_TRAP;
- }
-
- /* Now, compare the trap address to the unimplemented trap address. */
- trap1 = (long)NGetTrapAddress(trapNum, trapType);
- trap2 = (long)NGetTrapAddress(UNIMPL_TRAP, ToolTrap);
- if (trap1 == trap2)
- return(FALSE);
- else
- return(TRUE);
- }
-
-
- static OSErr GetFileFromRefNum (short fRefNum, short *volID, long *dirID, StringPtr name)
- {
- OSErr err;
- FCBPBPtr fcbInfoPtr;
-
- fcbInfoPtr = (void*)NewPtrSysClear(sizeof(FCBPBRec));
- if (!(err = MemError())) {
- fcbInfoPtr->ioRefNum = fRefNum;
- fcbInfoPtr->ioNamePtr = name;
- err = PBGetFCBInfoSync(fcbInfoPtr);
- if (!err) {
- *volID = fcbInfoPtr->ioVRefNum;
- if (*volID == 0) *volID = 0xFFFF; // means the system disk!
- *dirID = fcbInfoPtr->ioFCBParID;
- }
- }
-
- DisposePtr((Ptr)fcbInfoPtr);
-
- return err;
- }
-